package com.chenjim.glrecorder.filter;

import android.content.Context;
import android.opengl.GLES20;
import android.opengl.Matrix;


import com.chenjim.glrecorder.OpenGLUtils;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

/**
 * @author Lance
 * @date 2018/10/31
 */
public abstract class AbstractFilter {

    protected FloatBuffer mGLVertexBuffer;
    protected FloatBuffer mGLTextureBuffer;

    //顶点着色
    protected int mVertexShaderId;
    //片段着色
    protected int mFragmentShaderId;


    protected int mGLProgramId;
    /**
     * 顶点着色器
     * attribute vec4 position;
     * 赋值给gl_Position(顶点)
     */
    protected int vPosition;
    /**
     * varying vec2 textureCoordinate;
     */
    protected int vCoord;


    /**
     * uniform mat4 vMatrix;
     */
    protected int vMatrix;

    /**
     * 片元着色器
     * Samlpe2D 扩展 samplerExternalOES
     */
    protected int vTexture;

    protected int u_Matrix;


    protected int mOutputWidth;
    protected int mOutputHeight;
    private int vboId;

    public AbstractFilter(Context context, int vertexShaderId, int fragmentShaderId) {
        this.mVertexShaderId = vertexShaderId;
        this.mFragmentShaderId = fragmentShaderId;
        // 4个点 x，y = 4*2 float 4字节 所以 4*2*4
        mGLVertexBuffer = ByteBuffer.allocateDirect(4 * 2 * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        mGLVertexBuffer.clear();
        float[] VERTEX = {
                -1.0f, -1.0f,
                1.0f, -1.0f,
                -1.0f, 1.0f,
                1.0f, 1.0f
        };
        mGLVertexBuffer.put(VERTEX);


        mGLTextureBuffer = ByteBuffer.allocateDirect(4 * 2 * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        mGLTextureBuffer.clear();
        float[] TEXTURE = {
                0.0f, 1.0f,
                1.0f, 1.0f,
                0.0f, 0.0f,
                1.0f, 0.0f
        };
        mGLTextureBuffer.put(TEXTURE);


        initilize(context);
        initCoordinate();
    }


    protected void initilize(Context context) {
        String vertexShader = OpenGLUtils.readRawTextFile(context, mVertexShaderId);
        String fragmentShader = OpenGLUtils.readRawTextFile(context, mFragmentShaderId);
        mGLProgramId = OpenGLUtils.loadProgram(vertexShader, fragmentShader);
        // 获得着色器中的 attribute 变量 position 的索引值
        vPosition = GLES20.glGetAttribLocation(mGLProgramId, "vPosition");
        vCoord = GLES20.glGetAttribLocation(mGLProgramId, "vCoord");
        vMatrix = GLES20.glGetUniformLocation(mGLProgramId, "vMatrix");
        // 获得Uniform变量的索引值
        vTexture = GLES20.glGetUniformLocation(mGLProgramId, "vTexture");
        u_Matrix = GLES20.glGetUniformLocation(mGLProgramId, "u_Matrix");
    }


    public void onReady(int width, int height) {
        mOutputWidth = width;
        mOutputHeight = height;

        int[] vbos = new int[1];
        //创建vbo，生成一个，偏移量为0
        GLES20.glGenBuffers(1, vbos, 0);
        vboId = vbos[0];
        //绑定vbo
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
        //分配VBO需要的缓存大小，data=null是只需要申请空间，暂时不赋值
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 8 * 4 + 8 * 4, null, GLES20.GL_STATIC_DRAW);
        mGLVertexBuffer.position(0);
        mGLTextureBuffer.position(0);

        //为VBO设置顶点数据的值
        GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0, 8 * 4, mGLVertexBuffer);
        GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 8 * 4, 8 * 4, mGLTextureBuffer);
        //解绑vbo
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    }


    public void release() {
        GLES20.glDeleteProgram(mGLProgramId);
    }


    public int onDrawFrame(int textureId) {
        //设置显示窗口
        GLES20.glViewport(0, 0, mOutputWidth, mOutputHeight);

        //使用着色器
        GLES20.glUseProgram(mGLProgramId);

        //传递坐标
       /* GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 0, mGLVertexBuffer);
        GLES20.glEnableVertexAttribArray(vPosition);

        GLES20.glVertexAttribPointer(vCoord, 2, GLES20.GL_FLOAT, false, 0, mGLTextureBuffer);
        GLES20.glEnableVertexAttribArray(vCoord);*/

        //使用vbo，绑定，在顶点和纹理赋值之前
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);

        //顶点赋值
        GLES20.glEnableVertexAttribArray(vPosition);
        //GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer);
        //从vbo中取数据
        GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 8, 0);


        //纹理赋值
        GLES20.glEnableVertexAttribArray(vCoord);
        //GLES20.glVertexAttribPointer(fPosition, 2, GLES20.GL_FLOAT, false, 8, fragmentBuffer);
        //从vbo中取数据
        GLES20.glVertexAttribPointer(vCoord, 2, GLES20.GL_FLOAT, false, 8, 8 * 4);


        GLES20.glUniformMatrix4fv(u_Matrix, 1, false, getTransformationMatrix(0), 0);

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
        GLES20.glUniform1i(vTexture, 0);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
        //解绑vbo
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);

        return textureId;
    }


    public float[] getTransformationMatrix(int sensorOrientation) {
        float[] matrix = new float[16];
        Matrix.setIdentityM(matrix, 0);

        switch (sensorOrientation) {
            case 90:
                Matrix.rotateM(matrix, 0, 90, 0, 0, 1);
                break;
            case 180:
                Matrix.rotateM(matrix, 0, 180, 0, 0, 1);
                break;
            case 270:
                Matrix.rotateM(matrix, 0, 270, 0, 0, 1);
                break;
            default:
                break;
        }
        return matrix;
    }

    //修改坐标
    protected void initCoordinate() {

    }

}
